<template>
  <div>
    <div class="video-wrapper">
      <div>
        <video ref="localVideo" autoplay controls/>
      </div>
      <div>
        <video ref="remoteVideo" autoplay/>
      </div>
    </div>
    <div class="controls">
      <el-form ref="form" label-width="80px">
        <el-form-item label="房间id">
          <el-col :span="7">
            <el-input v-model="roomId"></el-input>
          </el-col>
        </el-form-item>
        <el-form-item label="用户id">
          <el-col :span="7">
            <el-input v-model="userId"></el-input>
          </el-col>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="joinMeeting">加入会议</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>

export default {
  name: 'VideoMeeting',
  data() {
    return {
      roomId: null,
      userId: null,
      fromId: null,
      hasSub: false,
      joining: false,
      localStream: new MediaStream(),
      remoteStream: null,
      peerConnection: new RTCPeerConnection({
        iceServers: [
          {urls: 'stun:stun.l.google.com:19302'},
          {urls: 'stun:stun1.l.google.com:19302'},
          {urls: 'stun:stun2.l.google.com:19302'}
        ]
      }),
    }
  },
  methods: {
    //获取音视频流
    async getAVStream() {
      return await navigator.mediaDevices.getUserMedia({video: true, audio: true});
    },

    async createPeerConnection() {
      // if (this.peerConnection) {
      //   return
      // }
      // // 配置STUN服务器
      // const configuration = {
      //   iceServers: [
      //     {urls: 'stun:stun.l.google.com:19302'},
      //     {urls: 'stun:stun1.l.google.com:19302'},
      //     {urls: 'stun:stun2.l.google.com:19302'}
      //   ]
      // };
      // this.peerConnection = new RTCPeerConnection(configuration);

      this.peerConnection.onicecandidate = (event) => {
        if (event.candidate) {
          console.log(`发送ICE候选者`)
          this.$natsClient.pub(`$request.$get.*.v1.meeting.candidate`, {
            fromId: this.userId,
            toId: this.fromId,
            roomId: this.roomId,
            candidate: event.candidate
          })
        }
      };

      // 监听远程流
      this.peerConnection.ontrack = (event) => {
        console.log(`接收到来自${this.fromId}远程流`, event)
        this.remoteStream = event.streams[0];
        this.$refs.remoteVideo.srcObject = this.remoteStream;
      };

      this.peerConnection.onconnectionstatechange = () => {
        this.$message.info(`连接状态: ${this.peerConnection.connectionState}`);
      };

      this.peerConnection.oniceconnectionstatechange = () => {
        if (this.peerConnection.iceConnectionState === 'disconnected') {
          this.$message.error('连接已断开');
          // TODO 处理连接断开的逻辑
        }
      };
    },

    async joinMeeting() {
      if (this.joining) {
        return
      }
      if (!this.roomId || !this.userId) {
        this.$message.error('请输入房间id和用户id')
        return
      }
      this.joining = true
      this.userId = parseInt(this.userId)
      this.roomId = parseInt(this.roomId)
      if (!this.hasSub) {
        this.subMeetingEvent()
      }
      this.$nats.pub(`$request.$get.*.v1.meeting.join`, {
        userId: this.userId,
        roomId: this.roomId
      });
      // if (result.code !== 0) {
      //   this.$message.error(`加入会议失败: ${result.msg}`);
      // } else {
      // await this.openCamera();
      // }
      this.joining = false
    },

    async userJoined(join) {
      const {fromId} = join
      this.$message.success(`${fromId}加入会议`)
      this.fromId = fromId
      await this.createPeerConnection()
      await this.sendOffer();
    },

    async userOffer(offer) {
      const {fromId, description} = offer
      this.fromId = fromId
      console.log(`接收到来自${fromId}offer`)
      await this.createPeerConnection();
      await this.peerConnection.setRemoteDescription(new RTCSessionDescription(description));
      // 创建并设置本地描述
      const answer = await this.peerConnection.createAnswer();
      await this.peerConnection.setLocalDescription(answer);
      console.log(`发送answer`)
      this.$natsClient.pub(`$request.$get.*.v1.meeting.answer`, {
        fromId: this.userId,
        toId: fromId,
        roomId: this.roomId,
        description: this.peerConnection.localDescription
      })


      // this.peerConnection.setRemoteDescription(new RTCSessionDescription(description))
      //     .then(() => this.peerConnection.createAnswer())
      //     .then(answer => this.peerConnection.setLocalDescription(answer).then(() => answer))
      //     .then(() => {
      //       this.$nats.pub(`$request.$get.*.v1.meeting.answer`, {
      //         fromId: this.userId,
      //         toId: fromId,
      //         roomId: this.roomId,
      //         description: this.peerConnection.localDescription
      //       })
      //     })
      //     .catch(error => {
      //       this.$message.error(`处理offer失败: ${error.message}`);
      //     });
    },
    async userAnswer(answer) {
      const {fromId, description} = answer
      this.$message.success(`接收到来自${fromId}answer`)
      if (this.peerConnection) {
        await this.peerConnection.setRemoteDescription(new RTCSessionDescription(description))
      }
    },
    userCandidate(candidates) {
      const {fromId, candidate} = candidates
      console.log(`接收到来自${fromId}candidate`, candidate)
      if (this.peerConnection && candidate) {
        this.peerConnection.addIceCandidate(new RTCIceCandidate(candidate))
            .catch(error => {
              this.$message.error(`添加ICE候选失败: ${error.message}`);
            });
      }
    },
    userJoinResult(data) {
      const {code, msg} = data
      if (code !== 0) {
        this.$message.error(`加入会议失败: ${msg}`);
      } else {
        this.openCamera();
      }
    },
    subMeetingEvent() {
      this.$natsClient.sub(`$report.$data.*.v1.meeting.${this.userId}.join.result`, this.userJoinResult)
      this.$natsClient.sub(`$report.$data.*.v1.meeting.${this.roomId}.${this.userId}.join`, this.userJoined)
      this.$natsClient.sub(`$report.$data.*.v1.meeting.${this.roomId}.${this.userId}.offer`, this.userOffer)
      this.$natsClient.sub(`$report.$data.*.v1.meeting.${this.roomId}.${this.userId}.answer`, this.userAnswer)
      this.$natsClient.sub(`$report.$data.*.v1.meeting.${this.roomId}.${this.userId}.candidate`, this.userCandidate)
      this.hasSub = true
    },
    async sendOffer() {
      const offer = await this.peerConnection.createOffer();
      console.log("设置offer", offer)
      await this.peerConnection.setLocalDescription(offer);
      console.log(`发送offer`)
      this.$nats.pub(`$request.$get.*.v1.meeting.offer`, {
        fromId: this.userId,
        toId: this.fromId,
        roomId: this.roomId,
        description: offer
      })

      // this.peerConnection.createOffer()
      //     .then(offer => {
      //       // 确保 setLocalDescription 完成后再进行后续操作
      //       return this.peerConnection.setLocalDescription(offer).then(() => offer);
      //     }).then(() => {
      //   const offer = this.peerConnection.localDescription;
      //   console.log("设置offer", offer)
      //   this.$message.success(`发送offer`)
      //   this.$nats.pub(`$request.$get.*.v1.meeting.offer`, {
      //     fromId: this.userId,
      //     toId: this.fromId,
      //     roomId: this.roomId,
      //     description: offer
      //   })
      // }).catch(error => {
      //   this.$message.error(`创建offer失败: ${error.message}`);
      // });
    },
    async openCamera() {
      this.localStream = await this.getAVStream();
      this.localStream.getTracks().forEach(track => {
        this.peerConnection.addTrack(track, this.localStream);
      });
      this.$refs.localVideo.srcObject = this.localStream;
    },
  },
  async mounted() {
      // console.log(await login())
      // console.log(await login())
  }
}
</script>


<style scoped>
.video-wrapper {
  display: flex;
}

.video-wrapper div {
  width: 300px;
  height: 300px;
  margin: 10px;
  border: 1px solid #000;
  border-radius: 5px;
}

video {
  width: 300px;
  height: 300px;

}
</style>